package cn.com.obs;

import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.admin.MinioAdminClient;
import io.minio.admin.UserInfo;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * Minio策略管理器
 *
 * @author LiuGuodong
 * @date 2024/06/06
 */
@Slf4j
public class MinioManager {

    private MinioAdminClient adminClient;
    private MinioClient minioClient;

    public MinioManager(String endpoint, String accessKey, String secretKey) {

        this.adminClient = MinioAdminClient.builder()
                                           .endpoint(endpoint)
                                           .httpClient(getUnsafeOkHttpClient())
                                           .credentials(accessKey, secretKey)
                                           .build();

        this.minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .httpClient(getUnsafeOkHttpClient())
                .build();
    }

    public static OkHttpClient getUnsafeOkHttpClient() {
        try {
            // 创建一个不验证证书链的TrustManager
            final TrustManager[] trustAllCerts = new TrustManager[] {
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[] {};
                        }
                    }
            };

            // 安装全信任的TrustManager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // 创建一个不进行主机名验证的HostnameVerifier
            final HostnameVerifier hostnameVerifier = (hostname, session) -> true;

            // 构建一个OkHttpClient实例
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]);
            builder.hostnameVerifier(hostnameVerifier);
            builder.connectTimeout(30, TimeUnit.SECONDS);
            builder.readTimeout(30, TimeUnit.SECONDS);
            builder.writeTimeout(30, TimeUnit.SECONDS);
            return builder.build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成上传凭证
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @return {@link String }
     */
    public String getUploadUrl(String bucketName, String objectName) {
        try {


            return minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.PUT)
                            .bucket(bucketName)
                            .object(objectName)
                            .expiry(60 * 60 * 24)
                            .build()
            );

        } catch (Exception e) {
            log.error("Error getting presigned object URL: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 创建策略
     *
     * @param policyName 策略名称
     * @param policyDocument 策略Json
     */
    public void createPolicy(String policyName, String policyDocument) {
        try {
            adminClient.addCannedPolicy(policyName, policyDocument);
        } catch (Exception e) {
            log.error("Error creating policy: {}", e.getMessage());
        }
    }


    /**
     * 删除策略
     *
     * @param policyName 策略名称
     */
    public void deletePolicy(String policyName) {
        try {
            adminClient.removeCannedPolicy(policyName);
        } catch (Exception e) {
            log.error("Error removing policy: {}", e.getMessage());
        }
    }


    /**
     * 列出策略
     *
     * @return {@link Map }<{@link String 策略名称}, {@link String 策略Json}>
     */// 列出策略
    public Map<String, String> listPolicies() {
        try {
            Map<String, String> policies = adminClient.listCannedPolicies();
            policies.forEach((key, policyInfo) -> {
                System.out.println("Policy: " + key + ", Document: " + policyInfo);
            });
            return policies;
        } catch (Exception e) {
            log.error("Error listing policies: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 获取策略
     *
     * @param policiesName 策略名称
     *
     * @return 策略Json
     */
    public void getPolicy(String policiesName) {
        Optional.ofNullable(listPolicies()).orElse(new HashMap<>()).get(policiesName);
    }

    /**
     * 创建用户
     *
     * @param accessKey 访问密钥
     * @param status 地位
     * @param secretKey 密钥
     * @param policyName 策略名称
     * @param memberOf 成员
     */// 创建用户
    public void createUser(String accessKey, UserInfo.Status status, String secretKey, String policyName, List<String> memberOf) {
        try {
            adminClient.addUser(accessKey, status, secretKey, policyName, memberOf);
        } catch (Exception e) {
            log.error("Error creating user: {}", e.getMessage());
        }
    }

    // 删除用户
    public void removeUser(String accessKey) {
        try {
            adminClient.deleteUser(accessKey);
        } catch (Exception e) {
            log.error("Error removing user: {}", e.getMessage());
        }
    }

    /**
     * 查看所有用户
     *
     * @return {@link Map }<{@link String }, {@link UserInfo }>
     */
    public Map<String, UserInfo> listUsers() {
        try {
            return adminClient.listUsers();

        } catch (Exception e) {
            log.error("Error listing users: {}", e.getMessage());
        }
        return null;
    }


    /**
     * 获取用户信息
     *
     * @param userName 管理
     *
     * @return {@link UserInfo }
     */
    public UserInfo getUserInfo(String userName) {
        try {
            return adminClient.getUserInfo(userName);
        } catch (Exception e) {
            log.error("Error getting user info: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 设置策略
     *
     * @param policiesName 策略名称
     * @param userName 用户名
     */
    public void setPolicy(String policiesName, String userName) {
        try {
            adminClient.setPolicy(userName, false, policiesName);
        } catch (Exception e) {
            log.error("Error setting policy: {}", e.getMessage());
        }
    }
}
